package org.yi.fc.config;

import java.io.File;
import java.io.FilenameFilter;
import java.util.List;

import org.apache.commons.configuration.ConfigurationException;
import org.beetl.core.GroupTemplate;
import org.beetl.ext.jfinal.BeetlRenderFactory;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yi.fc.cache.GlobalCache;
import org.yi.fc.controller.IndexController;
import org.yi.fc.controller.admin.column.ColumnController;
import org.yi.fc.controller.admin.content.ContentController;
import org.yi.fc.controller.admin.content.ContentTypeController;
import org.yi.fc.controller.admin.friendlink.FriendLinkController;
import org.yi.fc.controller.admin.login.LoginController;
import org.yi.fc.controller.comment.CommentController;
import org.yi.fc.entity.FColumn;
import org.yi.fc.entity.FComment;
import org.yi.fc.entity.FContent;
import org.yi.fc.entity.FContentType;
import org.yi.fc.entity.FFriendLink;
import org.yi.fc.entity.FSysUser;
import org.yi.fc.ext.beetl.tag.ColumnListTag;
import org.yi.fc.ext.beetl.tag.ColumnOptionTag;
import org.yi.fc.ext.beetl.tag.ForEachTag;
import org.yi.fc.handler.BaseHandler;
import org.yi.fc.helper.RouteHelper;
import org.yi.fc.interceptor.SessionInterceptor;
import org.yi.fc.model.Route;
import org.yi.fc.utils.FileUtils;
import org.yi.fc.utils.PropertiesUtils;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.druid.DruidPlugin;

/**
 * JFinal初始化配置
 * @author qq
 *
 */
public class InitConfig extends JFinalConfig {
	
	private static final Logger logger = LoggerFactory.getLogger(InitConfig.class);

	/**
	 * 配置常量
	 */
	@Override
	public void configConstant(Constants me) {
		
		logger.trace("config constants...");
		
		// 加载数据库配置
		loadPropertyFile("jdbc.properties");
		
		File configFile = FileUtils.locateAbsolutePathFromClasspath("fc.properties");
		try {
			GlobalCache.config = PropertiesUtils.load(configFile.getName(), "utf-8");
		} catch (ConfigurationException e) {
			logger.error("load fc.properties error!");
		}
		
		BeetlRenderFactory brf = new BeetlRenderFactory();
		//注册标签
		GroupTemplate gt = BeetlRenderFactory.groupTemplate;
		gt.registerTag("fc.foreach", ForEachTag.class);
		gt.registerTag("fc.columnOption", ColumnOptionTag.class);
		gt.registerTag("fc.columnList", ColumnListTag.class);
		
		me.setMainRenderFactory(brf);
		
		me.setDevMode(getPropertyToBoolean("devMode", false));
	}

	/**
	 * 配置路由
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void configRoute(final Routes me) {
		
		logger.trace("config route ...");
		
		// 加载基础路由
		me.add("/", IndexController.class)
			.add("/admin", LoginController.class)
			.add("/admin/content", ContentController.class)
			.add("/admin/contentType", ContentTypeController.class)
			.add("/admin/column", ColumnController.class)
			.add("/admin/friendlink", FriendLinkController.class)
			.add("/comment", CommentController.class);
		
		// 加载插件中的路由配置
		File routeFileDir = FileUtils.locateAbsolutePathFromClasspath("routes");
		if(routeFileDir != null) {
			String[] routeFile = routeFileDir.list(new FilenameFilter() {
				
				@Override
				public boolean accept(File dir, String name) {
					if(name.endsWith(".xml")) {
						return true;
					}
					return false;
				}
			});
			for(String file : routeFile) {
				try {
					List<Route> routes = RouteHelper.loadRoute(new File(file));
					for(Route r : routes) {
						me.add(RouteHelper.getControllerKey(r), 
								(Class<? extends Controller>) Class.forName(r.getClazz()));
					}
				} catch (DocumentException e) {
					logger.error("load route file error!", e);
				} catch (ClassNotFoundException e) {
					logger.error("Cast class error!", e);
				}
			}
		}
	}

	/**
	 * 配置插件
	 */
	@Override
	public void configPlugin(Plugins me) {
		
		logger.trace("config plugin...");
		
		DruidPlugin dp=new DruidPlugin(getProperty("jdbc.url"), 
				getProperty("jdbc.username"), getProperty("jdbc.password"),getProperty("jdbc.driverClassName"));
		
		dp.addFilter(new StatFilter());
		
		dp.setInitialSize(getPropertyToInt("db.initialSize", 10));
		dp.setMinIdle(getPropertyToInt("db.minIdle", 10));
		dp.setMaxActive(getPropertyToInt("max.active", 100));
		dp.setMaxWait(getPropertyToInt("db.maxWait", 60000));
		dp.setTimeBetweenEvictionRunsMillis(getPropertyToInt("db.timeBetweenEvictionRunsMillis", 120000));
		dp.setMinEvictableIdleTimeMillis(getPropertyToInt("db.minEvictableIdleTimeMillis", 120000));
		
		WallFilter wall = new WallFilter();
		wall.setDbType(getProperty("db.type"));
		dp.addFilter(wall);
		me.add(dp);
		
		ActiveRecordPlugin activeRecord = new ActiveRecordPlugin(dp);
		activeRecord.setDialect(new MysqlDialect());
		
		//后期开启
//		me.add(new EhCachePlugin());
		
		mapping(activeRecord);
		
		me.add(activeRecord);
		loadExtraPlugins(me);
	}

	/**
	 * 加载插件目录中的插件
	 * @param me
	 */
	private void loadExtraPlugins(Plugins me) {
		// TODO 加载插件目录中的插件
		
	}

	/**
	 * 配置实体-表映射
	 * 以后多了可以考虑做成xml或者annotation
	 * @param activeRecord
	 */
	private void mapping(ActiveRecordPlugin activeRecord) {
		activeRecord.addMapping("f_sys_user", FSysUser.class)
					.addMapping("f_content", FContent.class)
					.addMapping("f_content_type", FContentType.class)
					.addMapping("f_column", FColumn.class)
					.addMapping("f_friend_link", FFriendLink.class)
					.addMapping("f_comment", FComment.class);
		
		loadExtraMapping(activeRecord);
	}

	/**
	 * 插件需要单独建立实体类映射文件， 此处按照插件配置文件中的配置进行加载
	 * @param activeRecord
	 */
	private void loadExtraMapping(ActiveRecordPlugin activeRecord) {
		
		logger.trace("load extra mapping...");
		// TODO 加载插件目录中的实体映射
		
	}

	/**
	 * 配置拦截器
	 */
	@Override
	public void configInterceptor(Interceptors me) {
		
		logger.trace("config interceptor...");
		
		//判断用户是否登陆
		me.add(new SessionInterceptor());
		//关联beetl的session输出
		me.add(new SessionInViewInterceptor());
		//自动注入
//		me.add(new AutoInjectInterceptor());
	}

	/**
	 * 配置处理器
	 */
	@Override
	public void configHandler(Handlers me) {
		
		logger.trace("config handler...");
		
		me.add(new BaseHandler());
	}

}
